1 00:00:00,830 --> 00:00:01,550 Welcome. 2 00:00:01,550 --> 00:00:05,960 In this lecture, we're going to be checking out another service called the Collection Service. 3 00:00:05,960 --> 00:00:12,170 The purpose of the collection service is to give us the ability to add something called tags to instances 4 00:00:12,170 --> 00:00:13,070 in our game. 5 00:00:13,070 --> 00:00:19,880 A tag is simply a string that is attached to an instance, and these tags make it easier for us to uphold 6 00:00:19,880 --> 00:00:23,690 programming principles like dry or don't repeat yourself. 7 00:00:23,690 --> 00:00:28,610 This is because the collection service has functions where we are able to grab all of the instances 8 00:00:28,610 --> 00:00:33,860 in our game that have a specific tag, making it much easier for us to interact with these instances 9 00:00:33,860 --> 00:00:36,080 without needing to store them in folders. 10 00:00:36,470 --> 00:00:42,110 Here in the Roblox API documentation, it describes the collection service as something that manages 11 00:00:42,110 --> 00:00:45,320 groups or collections of instances with tags. 12 00:00:45,320 --> 00:00:51,500 Tags are sets of strings applied to objects that replicate from the server to the client, and in Team 13 00:00:51,500 --> 00:00:51,950 create. 14 00:00:51,950 --> 00:00:55,280 They are also serialized when places are saved. 15 00:00:55,280 --> 00:01:00,320 At the moment, tags are not visible within Roblox studio except with the use of a tag. 16 00:01:00,320 --> 00:01:01,340 Editing plugin. 17 00:01:01,340 --> 00:01:07,970 This is actually not true because Roblox Studio did update recently where we can now edit tags, uh, 18 00:01:07,970 --> 00:01:13,460 directly on instances through the properties panel, and we don't necessarily need to use a tag editing 19 00:01:13,460 --> 00:01:14,000 plugin. 20 00:01:14,000 --> 00:01:18,890 However, tag editing plugins do have more features, so if you'd like to use that, I've also attached 21 00:01:18,890 --> 00:01:20,150 one to this lecture. 22 00:01:20,920 --> 00:01:22,060 Back in Roblox studio. 23 00:01:22,060 --> 00:01:27,940 If I'd like to add a tag to an instance such as the spawn plate right here, I can select the spawn 24 00:01:27,940 --> 00:01:33,310 location, and then I can go to my properties panel and scroll all the way down until I reach the tags 25 00:01:33,310 --> 00:01:34,000 section. 26 00:01:34,000 --> 00:01:38,050 Here I am able to add new strings that are going to be my tags. 27 00:01:38,050 --> 00:01:43,300 For example, I could name this tag example tag and I can create it. 28 00:01:43,300 --> 00:01:48,820 And now I have this new tag that has been created on my spawn location. 29 00:01:49,060 --> 00:01:53,500 If I wanted to add this to like my base plate, then I can hit the plus button here. 30 00:01:53,500 --> 00:01:56,410 And as you can see, my example tag shows up right there. 31 00:01:57,480 --> 00:02:03,540 Another way that we can add tags to instances in our game is by using a tag editing plugin. 32 00:02:03,630 --> 00:02:08,250 So I've attached this tag editing plugin to the lecture and we can go ahead and open it up. 33 00:02:08,340 --> 00:02:10,650 And right here we can create a new tag. 34 00:02:10,680 --> 00:02:12,720 I'll create another example tag. 35 00:02:12,900 --> 00:02:16,170 And now here it shows my example tag in this menu. 36 00:02:16,170 --> 00:02:17,640 And I can go ahead and select it. 37 00:02:17,640 --> 00:02:22,770 And it gives me some extra options within this uh plugin to like change the icon. 38 00:02:22,770 --> 00:02:26,580 I can change the color when we want to visualize them in our game. 39 00:02:26,580 --> 00:02:32,130 So we actually have the option to see all the instances in our game as like a highlight. 40 00:02:32,130 --> 00:02:38,790 So if I select my part here, as you can see this check box shows up and I can select that checkbox. 41 00:02:38,790 --> 00:02:42,840 And now I have added this example tag to my spawn location. 42 00:02:42,930 --> 00:02:46,080 And as you can see it also shows up within our properties menu. 43 00:02:47,170 --> 00:02:53,590 And then if I wanted to visualize all of the items in my workspace that have this tag, I can go to 44 00:02:53,590 --> 00:02:54,640 World View. 45 00:02:54,820 --> 00:03:00,430 And as you can see, since I have this one selected, any instances in my game that have this example 46 00:03:00,430 --> 00:03:02,560 tag are going to be highlighted purple. 47 00:03:02,560 --> 00:03:06,160 And of course I can change this color to whatever I'd like as well. 48 00:03:06,760 --> 00:03:10,900 This is just the extra features that a tag editing plugin has. 49 00:03:10,900 --> 00:03:15,400 They aren't necessary, but they are a lot more useful in some situations. 50 00:03:15,950 --> 00:03:22,490 Now an example application of using tags in our game is for example, creating kill bricks, and a common 51 00:03:22,490 --> 00:03:28,490 approach would be to create our kill brick part, and then we would create a script inside of that part 52 00:03:28,490 --> 00:03:31,700 that would reference the part, and then listen to its touched event. 53 00:03:31,700 --> 00:03:34,400 And whenever a player touches it, we kill the player. 54 00:03:34,820 --> 00:03:38,510 So what we're going to do here is we're just going to create a kill brick real quick. 55 00:03:38,510 --> 00:03:39,950 We'll create a new part. 56 00:03:39,950 --> 00:03:41,840 I'll make sure this part is anchored. 57 00:03:41,840 --> 00:03:44,030 I'll change the color to something like red. 58 00:03:44,600 --> 00:03:48,290 And I can just name this my kill brick. 59 00:03:48,740 --> 00:03:52,850 And typically what we would do is we would add a script inside of our kill brick. 60 00:03:52,850 --> 00:03:56,090 And inside of here we would make a reference to our kill brick. 61 00:03:56,090 --> 00:04:00,260 I'll create a variable called brick and that's simply script dot parent. 62 00:04:01,070 --> 00:04:07,040 And then from this we would refer to our brick, get the touched event and connect a function to listen 63 00:04:07,040 --> 00:04:08,390 to that event. 64 00:04:08,390 --> 00:04:14,540 We would get the other part that touched our part, and then we could check if a humanoid touched our 65 00:04:14,540 --> 00:04:15,020 brick. 66 00:04:15,020 --> 00:04:17,450 So we would create a variable called humanoid. 67 00:04:17,450 --> 00:04:24,290 And what we would do is we would get other part dot parent, which would be the model of a character 68 00:04:24,290 --> 00:04:25,490 if a player touched it. 69 00:04:25,490 --> 00:04:30,680 And to confirm that we want to find, uh, the first child, which is a humanoid. 70 00:04:30,980 --> 00:04:38,330 So if the parent of this part has a humanoid inside of it, then we know that this is a player's character. 71 00:04:38,330 --> 00:04:41,840 And what we could do is we can check if it found a humanoid. 72 00:04:41,840 --> 00:04:46,070 If it did, then we can set the humanoid health equal to zero. 73 00:04:46,070 --> 00:04:48,440 And now we have scripted our kill brick. 74 00:04:49,690 --> 00:04:51,610 So now if we go and play our game. 75 00:04:53,700 --> 00:04:57,120 And I were to go walk over to my Kubrick. 76 00:04:57,120 --> 00:04:59,730 As you can see, it successfully killed me. 77 00:05:00,570 --> 00:05:06,600 Now, if I wanted to have multiple of these bricks, then my first thought may be to just copy and paste 78 00:05:06,600 --> 00:05:08,520 or duplicate this part multiple times. 79 00:05:08,520 --> 00:05:09,750 I'll just put one here. 80 00:05:09,750 --> 00:05:12,150 I could put one here, duplicate it here. 81 00:05:12,150 --> 00:05:18,030 Because usually if you're creating an orb game, you might have hundreds of these kill bricks. 82 00:05:18,480 --> 00:05:25,260 However, this is a big problem because now we have multiple scripts that are responsible for handling 83 00:05:25,260 --> 00:05:26,370 our kill bricks. 84 00:05:26,370 --> 00:05:31,620 If we wanted to add any new features to our kill bricks in the future, then we would have to go and 85 00:05:31,620 --> 00:05:34,170 edit each one of these scripts inside of our kill bricks. 86 00:05:34,170 --> 00:05:39,000 And if you had hundreds of these kill bricks, that would be a very time consuming process. 87 00:05:39,700 --> 00:05:43,060 This is where the collection service can come to save the day. 88 00:05:43,060 --> 00:05:49,570 What we can do instead is we can tag these parts with a tag like Kill Brick, and then we can grab all 89 00:05:49,570 --> 00:05:54,190 of those tagged parts and connect to their touched events from a single script. 90 00:05:54,190 --> 00:06:00,130 Doing it that way is much easier and more efficient than copy and pasting the same script over and over. 91 00:06:00,130 --> 00:06:03,670 So what I'm going to do is I'm going to keep one kill brick. 92 00:06:03,760 --> 00:06:09,730 We're going to get rid of the script inside of it, and instead we're going to add a new tag to this 93 00:06:09,730 --> 00:06:10,510 kill brick. 94 00:06:10,900 --> 00:06:14,170 And we can just call this tag Kill Brick. 95 00:06:14,890 --> 00:06:19,930 And now we are able to duplicate this part as many times as we would like, because they're all going 96 00:06:19,930 --> 00:06:22,150 to have the same tag of Kill Brick. 97 00:06:22,690 --> 00:06:25,750 Then we can create a new script inside of server script service. 98 00:06:26,750 --> 00:06:30,440 I'm going to call this script my kill brick handler. 99 00:06:32,660 --> 00:06:36,620 Then we could go ahead and create a variable to store our collection service. 100 00:06:36,620 --> 00:06:39,050 So we'll call it collection service. 101 00:06:39,050 --> 00:06:43,790 And we're going to use the Get Service function to grab the collection service. 102 00:06:45,220 --> 00:06:50,410 And then to grab all of the instances in our game that have the kill brick tag. 103 00:06:50,410 --> 00:06:55,810 What we can do is we can create a variable, I'm going to call it bricks, and we're going to refer 104 00:06:55,810 --> 00:07:00,220 to the collection service and use a function inside of there called Get Tagged. 105 00:07:00,220 --> 00:07:04,600 And this is going to return an array of objects in the game with a given tag. 106 00:07:04,600 --> 00:07:11,560 In this case, the tag or the instances that we would like to grab would be the instances with the kill 107 00:07:11,590 --> 00:07:12,760 brick tag. 108 00:07:14,160 --> 00:07:20,130 Now that we have all of the instances in our game with this kill break tag, then we can loop through 109 00:07:20,130 --> 00:07:24,210 every single brick inside of bricks. 110 00:07:24,720 --> 00:07:29,670 And what we want to do is we want to listen to their touched event so we can do brick dot touched. 111 00:07:31,560 --> 00:07:36,840 And instead of creating a lambda function for every single brick in our game, because that would be 112 00:07:36,840 --> 00:07:38,670 kind of a waste of resources. 113 00:07:38,670 --> 00:07:45,780 Instead, what we want to do is we want to create a function we'll call it on touched, which will get 114 00:07:45,780 --> 00:07:48,960 passed the other part that touched a particular brick part. 115 00:07:48,960 --> 00:07:52,980 And then instead we can simply pass the reference to this function instead. 116 00:07:53,190 --> 00:07:59,340 That way, we aren't creating hundreds of lambda functions that are each listening to an individual 117 00:07:59,550 --> 00:07:59,910 brick. 118 00:07:59,910 --> 00:08:05,280 Instead, every single kill brick in our game are all going to refer back to one function, so that 119 00:08:05,280 --> 00:08:06,990 helps save on memory. 120 00:08:07,950 --> 00:08:11,280 And then inside of this function, we can do the exact same thing that we did before. 121 00:08:11,280 --> 00:08:16,020 We'll check to see if the parent of this other part has a humanoid inside of it. 122 00:08:20,450 --> 00:08:22,310 And if there is a humanoid. 123 00:08:22,940 --> 00:08:26,840 Then we're just going to set the humanoids health equal to zero. 124 00:08:28,030 --> 00:08:32,500 Now, if we go and play test the game, each one of these bricks should be able to kill me. 125 00:08:32,500 --> 00:08:38,980 Because again, they have the kill brick tag and our script collects all of the instances in our game 126 00:08:38,980 --> 00:08:43,480 with that tag, and we listen to each one of those bricks touched event. 127 00:08:43,480 --> 00:08:45,160 So let's go ahead and test this out. 128 00:08:48,560 --> 00:08:49,820 If I walk over to my part. 129 00:08:49,820 --> 00:08:50,840 As you can see. 130 00:08:50,840 --> 00:08:51,500 There we go. 131 00:08:51,500 --> 00:08:52,310 It killed me. 132 00:08:52,310 --> 00:08:53,780 Let's go ahead and test another one. 133 00:08:54,320 --> 00:08:57,080 Let's go ahead and try this left, brick. 134 00:08:57,110 --> 00:08:59,780 As you can see, that one killed me as well. 135 00:09:00,740 --> 00:09:02,570 And one more time, we'll go test. 136 00:09:02,570 --> 00:09:04,130 Maybe this one right here. 137 00:09:04,130 --> 00:09:06,560 And as you can see, it has killed me. 138 00:09:06,560 --> 00:09:07,550 Very cool. 139 00:09:08,540 --> 00:09:13,760 Now, instead of having four separate scripts in each one of these, kill bricks or kill bricks are 140 00:09:13,760 --> 00:09:18,650 now being handled by a singular script inside of server script service. 141 00:09:18,680 --> 00:09:23,750 This is why the collection service helps us with the dry principle, because we don't have to repeat 142 00:09:23,750 --> 00:09:28,280 ourselves, or we don't have to duplicate the same script over and over in our game. 143 00:09:28,850 --> 00:09:33,860 Now, another cool thing we can do with the collection service is we can listen for when a new instance 144 00:09:33,860 --> 00:09:36,110 gets added with a particular tag. 145 00:09:36,110 --> 00:09:41,780 That way, during the runtime of our game, if, let's say a new brick gets added by another script 146 00:09:41,780 --> 00:09:47,450 and we want that, uh, we want that part to be a kill brick, then what we could do is we could listen 147 00:09:47,450 --> 00:09:51,500 for when that part is added and then listen to its touched event. 148 00:09:51,500 --> 00:09:54,950 So inside of the collection service, there's an event we can get. 149 00:09:55,810 --> 00:10:00,970 And we get this event from a function called get instance added signal. 150 00:10:01,000 --> 00:10:08,680 So we would pass a tag which would return back to us an event that would fire every time a tag is added 151 00:10:08,680 --> 00:10:15,610 to an object in our game, or any instance in our game that has that particular tag added to it. 152 00:10:15,880 --> 00:10:21,760 In this case, the tag we want to listen to is our kill brick tag. 153 00:10:22,540 --> 00:10:25,180 And then we can go ahead and connect to this event. 154 00:10:25,180 --> 00:10:30,160 And what this event is going to pass to us is that particular instance in our game that had the kill 155 00:10:30,160 --> 00:10:31,480 brick tag added to it. 156 00:10:31,480 --> 00:10:33,190 So we'll just call it brick here. 157 00:10:33,460 --> 00:10:36,400 And then we can do the exact same thing that we did in our for loop. 158 00:10:36,400 --> 00:10:38,050 We're going to refer to the brick. 159 00:10:39,010 --> 00:10:40,480 Get its touched event. 160 00:10:40,480 --> 00:10:44,110 And then we're going to connect our on touched function. 161 00:10:44,950 --> 00:10:52,750 So now any time a new part is created in our game, or any time a part in our game has this kill brick 162 00:10:52,780 --> 00:10:58,780 tag added to it, this event's going to fire and this lambda function is going to execute, and that 163 00:10:58,780 --> 00:11:02,440 means we're going to connect to the touched event of that particular part. 164 00:11:02,440 --> 00:11:05,590 And that means it should kill our player. 165 00:11:05,590 --> 00:11:10,600 So to test this out, what we're going to do is we're going to play test the game. 166 00:11:12,740 --> 00:11:17,480 So as you can see right now, our game is running and I'm going to switch to the server view. 167 00:11:17,750 --> 00:11:20,780 And I'm going to go ahead and duplicate one of these bricks. 168 00:11:20,780 --> 00:11:22,700 So I'm going to do control D. 169 00:11:22,910 --> 00:11:27,620 And now I've just created a new part during the runtime of our game. 170 00:11:27,830 --> 00:11:30,440 And that means that event should have fired. 171 00:11:30,440 --> 00:11:33,530 And this brick right here should also kill us. 172 00:11:33,830 --> 00:11:40,040 So if we go and touch it, as you can see, perfect, it works just fine. 173 00:11:40,550 --> 00:11:47,000 I'm also going to add a print statement in here we can print out something like New Kill brick was added. 174 00:11:47,000 --> 00:11:51,140 So that way you can actually see this event being fired inside of the console. 175 00:11:51,140 --> 00:11:53,030 So again if we go and play test. 176 00:11:54,760 --> 00:11:59,290 And we switch to the server view and we duplicate one of these parts right when I hit control. 177 00:11:59,290 --> 00:12:02,410 And D as you can see, new brick was added. 178 00:12:02,410 --> 00:12:05,740 And that means we're listening to the touch event for this new brick. 179 00:12:05,740 --> 00:12:07,120 Again we can duplicate it. 180 00:12:07,690 --> 00:12:09,250 New kill brick was added. 181 00:12:09,250 --> 00:12:14,800 We can duplicate it again and again and again and again. 182 00:12:14,800 --> 00:12:16,210 Very very cool. 183 00:12:17,200 --> 00:12:23,440 However, one small problem we might encounter is what if we would like to disable the functionality 184 00:12:23,440 --> 00:12:26,710 for a particular object in our game when a tag is removed? 185 00:12:26,710 --> 00:12:31,750 For example, if this part right here, let's say the tag of kill brick was removed. 186 00:12:31,780 --> 00:12:37,210 Well, when the tag of kill brick is removed, maybe we don't want this brick to kill anybody anymore. 187 00:12:37,210 --> 00:12:41,470 However, if we go and touch it, this brick still kills us. 188 00:12:41,470 --> 00:12:46,240 And that's because we're still listening to the touch event for this particular part, even though it 189 00:12:46,240 --> 00:12:48,490 doesn't have the kill brick tag anymore. 190 00:12:49,060 --> 00:12:55,600 A way that we could avoid doing this is by listening to another event in the collection service, and 191 00:12:55,600 --> 00:13:00,010 that event is get instance removing signal or removed signal. 192 00:13:00,010 --> 00:13:02,350 And this is again where we would pass a tag. 193 00:13:02,350 --> 00:13:07,720 And then the event would fire any time this given tag is removed from an instance. 194 00:13:08,860 --> 00:13:10,930 So we could pass kill brick here. 195 00:13:11,510 --> 00:13:16,160 And connect a function to get the brick when this event fires. 196 00:13:16,340 --> 00:13:21,500 And what we're going to have to do is we're going to have to store each of these connections. 197 00:13:21,500 --> 00:13:24,710 Because remember the connect function returns a connection. 198 00:13:24,710 --> 00:13:30,110 And then we're going to have to disconnect that function from our touched event any time. 199 00:13:30,230 --> 00:13:33,800 Uh one of these bricks has their tag removed. 200 00:13:34,160 --> 00:13:40,610 So what we could do is we could create a table and we're going to call it connections. 201 00:13:41,990 --> 00:13:46,640 And inside of this connections table, we're going to store a bunch of key value pairs. 202 00:13:46,670 --> 00:13:49,610 The key is going to be the part itself. 203 00:13:49,610 --> 00:13:55,340 While the value associated with that key is going to be the connection or the value that gets returned 204 00:13:55,340 --> 00:13:57,020 from our connect function. 205 00:13:57,380 --> 00:14:02,090 So what we're going to do when we loop through all of the bricks in our game, we're going to refer 206 00:14:02,090 --> 00:14:05,420 to our connections table, and we're going to create a new key. 207 00:14:05,420 --> 00:14:07,580 And that key is going to be our brick. 208 00:14:08,000 --> 00:14:12,020 And we're going to set that equal to the return from our connect function. 209 00:14:12,020 --> 00:14:17,480 So now we have stored all of the connections for each one of our bricks in our game. 210 00:14:18,080 --> 00:14:23,240 And we're also going to want to do this exact same thing for when a new brick is added. 211 00:14:23,240 --> 00:14:25,460 So we'll paste that in here as well. 212 00:14:26,360 --> 00:14:34,160 And now what we could do is we can check when this tag gets removed from an instance, and we can check 213 00:14:34,160 --> 00:14:38,450 if that instance has a connection inside of our connections table. 214 00:14:38,690 --> 00:14:46,880 So we can check if inside of our connections table we have a key for this particular instance. 215 00:14:46,880 --> 00:14:53,900 If we do, that means we need to go ahead and disconnect the function from that part's touched event 216 00:14:54,170 --> 00:15:01,160 so we can do connections, pass our key which is the brick, and then we can go ahead and disconnect. 217 00:15:02,460 --> 00:15:03,570 That connection. 218 00:15:03,570 --> 00:15:09,420 And then we can also copy this thing here again and then set it equal to nil, which essentially just 219 00:15:09,420 --> 00:15:13,200 removes this key from our connections table. 220 00:15:13,200 --> 00:15:19,980 So now any time we have a part in our game that gets set up and has the touch event, listen to. 221 00:15:20,520 --> 00:15:27,630 If that instance has the brick tag removed, then we disconnect the function listening to that touched 222 00:15:27,630 --> 00:15:30,990 event, which means the part is no longer going to kill any of our players. 223 00:15:32,010 --> 00:15:35,520 So we can go ahead and play test this and try it out. 224 00:15:37,700 --> 00:15:46,370 So if I check out this part right here, which has the Kubrick tag, if I go ahead and remove this Kubrick 225 00:15:46,400 --> 00:15:50,960 tag and I go back to the client, if I go and touch it, let's see if it kills me. 226 00:15:51,470 --> 00:15:57,380 As you can see, the part no longer kills me, and that's because that removes signal got fired, which 227 00:15:57,380 --> 00:16:02,900 allowed us to disconnect the function that was listening to the touched event from this particular part. 228 00:16:02,900 --> 00:16:05,510 However, this part right here will still kill me. 229 00:16:06,620 --> 00:16:09,860 This also works if we duplicate one of these kill bricks. 230 00:16:09,860 --> 00:16:14,930 So as you can see, we added a new kill brick, which means this is a dangerous part that will kill 231 00:16:14,930 --> 00:16:15,500 us. 232 00:16:15,500 --> 00:16:22,160 But if we go ahead and remove the tag from it and then we go and touch it, as you can see, it no longer 233 00:16:22,160 --> 00:16:22,970 kills us. 234 00:16:23,890 --> 00:16:29,200 The collection service is an incredibly powerful and useful tool at your disposal that you're going 235 00:16:29,200 --> 00:16:31,420 to be using a lot in your games. 236 00:16:31,600 --> 00:16:34,090 Keep up the good work and I'll see you in the next lecture.